/**
 * <copyright>
 * </copyright>
 *
 * $Id$
 */
package org.eclipse.bpel.model.impl;

import java.util.Collection;

import org.apache.log4j.Logger;
import org.eclipse.bpel.model.Activity;
import org.eclipse.bpel.model.ModelPackage;
import org.eclipse.bpel.model.Process;
import org.eclipse.bpel.model.VariableElement;
import org.eclipse.bpel.model.Writers;

import org.eclipse.emf.common.notify.Notification;

import org.eclipse.emf.common.util.EList;

import org.eclipse.emf.ecore.EClass;
import org.eclipse.emf.ecore.InternalEObject;

import org.eclipse.emf.ecore.impl.ENotificationImpl;
import org.eclipse.emf.ecore.impl.EObjectImpl;

import org.eclipse.emf.ecore.util.EObjectResolvingEList;

/**
 * <!-- begin-user-doc --> An implementation of the model object '
 * <em><b>Writers</b></em>'. <!-- end-user-doc -->
 * <p>
 * The following features are implemented:
 * <ul>
 * <li>{@link org.eclipse.bpel.model.impl.WritersImpl#getPoss <em>Poss</em>}</li>
 * <li>{@link org.eclipse.bpel.model.impl.WritersImpl#getInv <em>Inv</em>}</li>
 * <li>{@link org.eclipse.bpel.model.impl.WritersImpl#getDis <em>Dis</em>}</li>
 * <li>{@link org.eclipse.bpel.model.impl.WritersImpl#isMbd <em>Mbd</em>}</li>
 * </ul>
 * </p>
 * 
 * @generated
 */
public class WritersImpl extends EObjectImpl implements Writers {

	private static transient Logger log = Logger.getLogger(WritersImpl.class);

	/**
	 * The cached value of the '{@link #getPoss() <em>Poss</em>}' reference
	 * list. <!-- begin-user-doc --> <!-- end-user-doc -->
	 * 
	 * @see #getPoss()
	 * @generated
	 * @ordered
	 */
	protected EList<Activity> poss;

	/**
	 * The cached value of the '{@link #getInv() <em>Inv</em>}' reference list.
	 * <!-- begin-user-doc --> <!-- end-user-doc -->
	 * 
	 * @see #getInv()
	 * @generated
	 * @ordered
	 */
	protected EList<Activity> inv;

	/**
	 * The cached value of the '{@link #getDis() <em>Dis</em>}' reference list.
	 * <!-- begin-user-doc --> <!-- end-user-doc -->
	 * 
	 * @see #getDis()
	 * @generated
	 * @ordered
	 */
	protected EList<Activity> dis;

	/**
	 * The default value of the '{@link #isMbd() <em>Mbd</em>}' attribute. <!--
	 * begin-user-doc --> <!-- end-user-doc -->
	 * 
	 * @see #isMbd()
	 * @generated
	 * @ordered
	 */
	protected static final boolean MBD_EDEFAULT = false;

	/**
	 * The cached value of the '{@link #isMbd() <em>Mbd</em>}' attribute. <!--
	 * begin-user-doc --> <!-- end-user-doc -->
	 * 
	 * @see #isMbd()
	 * @generated
	 * @ordered
	 */
	protected boolean mbd = MBD_EDEFAULT;

	/**
	 * <!-- begin-user-doc --> <!-- end-user-doc -->
	 * 
	 * @generated
	 */
	protected WritersImpl() {
		super();
	}

	/**
	 * <!-- begin-user-doc --> <!-- end-user-doc -->
	 * 
	 * @generated
	 */
	@Override
	protected EClass eStaticClass() {
		return ModelPackage.Literals.WRITERS;
	}

	/**
	 * <!-- begin-user-doc --> <!-- end-user-doc -->
	 * 
	 * @generated
	 */
	public EList<Activity> getPoss() {
		if (poss == null) {
			poss = new EObjectResolvingEList<Activity>(Activity.class, this,
					ModelPackage.WRITERS__POSS);
		}
		return poss;
	}

	/**
	 * <!-- begin-user-doc --> <!-- end-user-doc -->
	 * 
	 * @generated
	 */
	public EList<Activity> getInv() {
		if (inv == null) {
			inv = new EObjectResolvingEList<Activity>(Activity.class, this,
					ModelPackage.WRITERS__INV);
		}
		return inv;
	}

	/**
	 * <!-- begin-user-doc --> <!-- end-user-doc -->
	 * 
	 * @generated
	 */
	public EList<Activity> getDis() {
		if (dis == null) {
			dis = new EObjectResolvingEList<Activity>(Activity.class, this,
					ModelPackage.WRITERS__DIS);
		}
		return dis;
	}

	/**
	 * <!-- begin-user-doc --> <!-- end-user-doc -->
	 * 
	 * @generated
	 */
	public boolean isMbd() {
		return mbd;
	}

	/**
	 * <!-- begin-user-doc --> <!-- end-user-doc -->
	 * 
	 * @generated
	 */
	public void setMbdGen(boolean newMbd) {
		boolean oldMbd = mbd;
		mbd = newMbd;
		if (eNotificationRequired())
			eNotify(new ENotificationImpl(this, Notification.SET,
					ModelPackage.WRITERS__MBD, oldMbd, mbd));
	}

	/**
	 * @generated NOT
	 */
	public void setMbd(boolean newMbd) {
		boolean oldMbd = mbd;
		mbd = newMbd;
		// log.trace("Mbd set to: " + mbd);
		if (eNotificationRequired())
			eNotify(new ENotificationImpl(this, Notification.SET,
					ModelPackage.WRITERS__MBD, oldMbd, mbd));
	}

	/**
	 * <!-- begin-user-doc --> <!-- end-user-doc -->
	 * 
	 * @generated
	 */
	@Override
	public Object eGet(int featureID, boolean resolve, boolean coreType) {
		switch (featureID) {
		case ModelPackage.WRITERS__POSS:
			return getPoss();
		case ModelPackage.WRITERS__INV:
			return getInv();
		case ModelPackage.WRITERS__DIS:
			return getDis();
		case ModelPackage.WRITERS__MBD:
			return isMbd() ? Boolean.TRUE : Boolean.FALSE;
		}
		return super.eGet(featureID, resolve, coreType);
	}

	/**
	 * <!-- begin-user-doc --> <!-- end-user-doc -->
	 * 
	 * @generated
	 */
	@SuppressWarnings("unchecked")
	@Override
	public void eSet(int featureID, Object newValue) {
		switch (featureID) {
		case ModelPackage.WRITERS__POSS:
			getPoss().clear();
			getPoss().addAll((Collection<? extends Activity>) newValue);
			return;
		case ModelPackage.WRITERS__INV:
			getInv().clear();
			getInv().addAll((Collection<? extends Activity>) newValue);
			return;
		case ModelPackage.WRITERS__DIS:
			getDis().clear();
			getDis().addAll((Collection<? extends Activity>) newValue);
			return;
		case ModelPackage.WRITERS__MBD:
			setMbd(((Boolean) newValue).booleanValue());
			return;
		}
		super.eSet(featureID, newValue);
	}

	/**
	 * <!-- begin-user-doc --> <!-- end-user-doc -->
	 * 
	 * @generated
	 */
	@Override
	public void eUnset(int featureID) {
		switch (featureID) {
		case ModelPackage.WRITERS__POSS:
			getPoss().clear();
			return;
		case ModelPackage.WRITERS__INV:
			getInv().clear();
			return;
		case ModelPackage.WRITERS__DIS:
			getDis().clear();
			return;
		case ModelPackage.WRITERS__MBD:
			setMbd(MBD_EDEFAULT);
			return;
		}
		super.eUnset(featureID);
	}

	/**
	 * <!-- begin-user-doc --> <!-- end-user-doc -->
	 * 
	 * @generated
	 */
	@Override
	public boolean eIsSet(int featureID) {
		switch (featureID) {
		case ModelPackage.WRITERS__POSS:
			return poss != null && !poss.isEmpty();
		case ModelPackage.WRITERS__INV:
			return inv != null && !inv.isEmpty();
		case ModelPackage.WRITERS__DIS:
			return dis != null && !dis.isEmpty();
		case ModelPackage.WRITERS__MBD:
			return mbd != MBD_EDEFAULT;
		}
		return super.eIsSet(featureID);
	}

	/**
	 * <!-- begin-user-doc --> <!-- end-user-doc -->
	 * 
	 * @generated
	 */
	@Override
	public String toString() {
		if (eIsProxy())
			return super.toString();

		StringBuffer result = new StringBuffer(super.toString());
		result.append(" (mbd: ");
		result.append(mbd);
		result.append(')');
		return result.toString();
	}

	@Override
	public void purgeDuplicatesOr() {
		EList<Activity> invList = getInv();
		EList<Activity> disList = getDis();
		EList<Activity> possList = getPoss();

		possList.removeAll(invList);
		disList.removeAll(invList);
		possList.removeAll(disList);
	}

	/**
	 * Line format is: ACTIVITY {'PRE' | 'POST'} VARIABLE_ELEMENT
	 * 'Poss:{'POSS_LIST'} Dis:{'DIS_LIST'} Inv:{'INV_LIST'} MBD:' MBD <br/>
	 * <br/>
	 * ACTIVITY ::= The activity of which the writers state is dumped here <br/>
	 * <br/>
	 * VARIABLE_ELEMENT ::= VARIABLE.getName() '-' VARIABLE.getQuery() <br/>
	 * <br/>
	 * POSS_LIST ::= all writing activities which are possible to write <br/>
	 * <br/>
	 * DIS_LIST ::= all writing activities which possibly disabled via Death
	 * Path Elimination (DPE) <br/>
	 * <br/>
	 * INV_LIST ::= all writing activities which are definitly overwritten <br/>
	 * <br/>
	 * MDB ::= May be dead state. Announces if this activity of which the
	 * writers state currently is dumped might be disabled via DPE
	 * 
	 * @param name
	 *            - is used as label only. You should enter the name of the
	 *            activity element that is dumped here.
	 * 
	 * @param ve
	 *            - the VariableElement for which the writers are estimated
	 *            during this execution of the analyser
	 * 
	 * @param pre - used to add the label PRE or POST to the output so that
	 * the output can be identified as pre or post writers
	 */
	@Override
	public void dump(/* Activity activity */String name, VariableElement ve,
			boolean pre) {
		StringBuilder sb = new StringBuilder();
		// sb.append(activity.getName());
		sb.append(name);
		sb.append(" ");

		if (pre) {
			sb.append("PRE");
		} else {
			sb.append("POST");
		}

		// VARIABLE_ELEMENT
		sb.append(" ");
		sb.append(ve.getVariable().getName());
		sb.append("-");
		
		// If not the entire variable is the variable element, but only
		// part of it, then the part has to be identified by a XPath Query.
		// This code adds the query to the output or Query-NotAvailable
		// if the entire variable forms the variable element
		if (null == ve.getQuery()) {
			sb.append("Query-NA");
		} else {
			sb.append(ve.getQuery());
		}

		EList<Activity> possList = getPoss();
		EList<Activity> disList = getDis();
		EList<Activity> invList = getInv();

		int i = 0;
		sb.append(" Poss: {");
		if (!possList.isEmpty()) {
			for (Activity act : possList) {

				if (0 != i) {
					sb.append(", ");
				}
				i++;
				sb.append(act.getName());
			}
		}
		i = 0;
		sb.append("} Dis: {");
		if (!disList.isEmpty()) {
			for (Activity act : disList) {
				if (0 != i) {
					sb.append(", ");
				}
				i++;
				sb.append(act.getName());
			}
		}
		i = 0;
		sb.append("} Inv: {");
		if (!invList.isEmpty()) {
			for (Activity act : invList) {
				if (0 != i) {
					sb.append(", ");
				}
				i++;
				sb.append(act.getName());
			}
		}

		sb.append("} MBD: ");
		sb.append(mbd);

		log.trace(sb.toString());

		if (!pre) {
			log
					.trace("***************************************************************");
		}
	}

	/*
	 * @Override public void dump(Process element, VariableElement
	 * variableElement, boolean pre) { StringBuilder sb = new StringBuilder();
	 * sb.append(element.getName()); sb.append(" ");
	 * 
	 * if (pre) { sb.append("PRE"); } else { sb.append("POST"); }
	 * 
	 * // VARIABLE_ELEMENT sb.append(" ");
	 * sb.append(variableElement.getVariable().getName()); sb.append("-");
	 * sb.append(variableElement.getQuery());
	 * 
	 * EList<Activity> possList = getPoss(); EList<Activity> disList = getDis();
	 * EList<Activity> invList = getInv();
	 * 
	 * sb.append(" Poss: {"); if (!possList.isEmpty()) { for (Activity act :
	 * possList) { sb.append(act.getName()); sb.append(" "); } }
	 * sb.append("} Dis: {"); if (!disList.isEmpty()) { for (Activity act :
	 * disList) { sb.append(act.getName()); sb.append(" "); } }
	 * sb.append("} Inv: {"); if (!invList.isEmpty()) { for (Activity act :
	 * invList) { sb.append(act.getName()); sb.append(" "); } }
	 * 
	 * sb.append("} MBD: "); sb.append(mbd);
	 * 
	 * log.trace(sb.toString());
	 * log.trace("***************************************************************"
	 * ); }
	 */

	@Override
	public boolean equals(Writers other) {

		if (this == other) {
			return true;
		}

		if (mbd != other.isMbd()) {
			return false;
		}

		if ((getPoss().size() != other.getPoss().size())
				|| (getDis().size() != other.getDis().size())
				|| (getInv().size() != other.getInv().size())) {
			return false;
		}

		for (Activity act : getPoss()) {
			if (!other.getPoss().contains(act)) {
				return false;
			}
		}
		for (Activity act : getDis()) {
			if (!other.getDis().contains(act)) {
				return false;
			}
		}
		for (Activity act : getInv()) {
			if (!other.getInv().contains(act)) {
				return false;
			}
		}

		return true;
	}

} // WritersImpl
